package com.xsir.jwt;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xsir.entity.User;
import com.xsir.mapper.PermissionMapper;
import com.xsir.mapper.RoleMapper;
import com.xsir.mapper.UserMapper;
import com.xsir.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author user
 * @date 2020/9/2
 */
@Slf4j
public class JwtRealm extends AuthorizingRealm {
    @Resource
    private UserMapper userMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private PermissionMapper permissionMapper;
    
    /**
     * 多重写一个support
     * 标识这个Realm是专门用来验证JwtToken
     * 不负责验证其他的token（UsernamePasswordToken）
     * @param token     从过滤器中传入的jwtToken
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }
    
    @Override
    public String getName() {
        return "JwtRealm";
    }
    
    /**
     * 执行授权逻辑
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 执行授权逻辑
        log.debug("正在执行授权逻辑...");
        
        // 1、获取用户的角色
        String jwt = principals.toString();
        String account = JwtUtil.decode(jwt).get("account", String.class);
        List<String> roles = roleMapper.getRoles(account);
        // 2、获取角色拥有的权限
        Set<String> assignPermissions = new HashSet<>();
        roles.forEach(r -> {
            List<String> permissions = permissionMapper.getPermissions(r);
            if(permissions != null) {
                assignPermissions.addAll(permissions);
            }
        });
        // 3、给当前用户分配角色和权限
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> assignRoles = new HashSet<>(roles);
        info.setRoles(assignRoles);
        info.setStringPermissions(assignPermissions);
        
        return info;
    }
    
    /**
     * 执行认证逻辑
     *
     * @param token   从过滤器中传入的jwtToken
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 执行认证逻辑
        log.debug("正在执行认证逻辑...");
        log.debug(((JwtToken)token).toString());
        
        // 1、获取jwt
        String jwt = (String)token.getPrincipal();
        // 2、校验jwt
        if(!JwtUtil.verify(jwt)) {
            throw new UnsupportedTokenException("无效的Token！");
        }
        // 3、jwt校验通过、把jwt交给doGetAuthorizationInfo执行授权操作
        return new SimpleAuthenticationInfo(jwt,jwt,"JwtRealm");
    }
}
